<?php
/**
 * Created by PhpStorm.
 * User: krystal
 * Date: 2019/3/20
 * Time: 16:23
 */

namespace app\api\controller\v9;


use app\api\controller\v2\Auth;
use app\api\controller\v4\CheckOrders;
use app\common\lib\exception\ApiException;
use app\common\lib\Orders as OrdersLib;
use app\common\lib\Util;
use app\common\model\Goods;
use app\common\model\Orders;
use app\common\model\ZhunleCourse;
use DateTime;
use Exception;
use think\Cache;
use think\Db;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\exception\DbException;
use think\Log;
use think\response\Json;

/**
 * 统一下单相关接口
 * Class OrdersPay
 * @package app\api\controller\v9
 */
class OrdersPay extends Auth
{
    /**
     * 统一下单入口
     * @param array $map
     * @return array|bool|Json
     * @throws ApiException
     * @throws Exception
     */
    public function pay_unlock($map = [])
    {
        $order_type = $map['order_type'];
        $trade_type = $map['trade_type'];
        $time = time();
        $uid = $this->user['id'];

        $gid = $map['gid'] ?? 0;
        //校准生辰下单参数
        $reid = $map['reid'] ?? 0;
        //运势下单参数
        $fid = 0;
        $rids = $map['rids'] ?? '';
        $start_time = $map['start_time'] ?? 0;//字符串类型
        $fortune_type = $map['fortune_type'] ?? 1;
        //地图下单参数
        $gids = isset($map['gids']) ? explode(',', $map['gids']) : '';
        $rid = $map['rid'] ?? 0;
        //视频下单参数
        $id = $map['id'] ?? 0;
        $openid = $map['openid'] ?? '';
        $callback_url = $map['callback_url'] ?? '';

        switch (true)
        {
            case $order_type == 1:
                $pay_des = '准了 - 校准生辰';
                $data = $this->pay_rec(['gid' => $gid, 'reid' => $reid]);
                $price = $data['price'];
                $type = 1;
                break;
            case in_array($order_type, [2, 3, 4]):
                $pay_des = '准了 - 运势';
                $data = $this->pay_fortune(['gid' => $gid, 'rids' => $rids, 'start_time' => $start_time, 'fortune_type' => $fortune_type]);
                $price = $data['price'];
                $fid = $data['fid'];
                $type = 2;
                break;
            case $order_type == 5:
                $pay_des = '准了 - 幸运之城';
                $data = $this->pay_map(['gids' => $gids, 'rid' => $rid]);
                $price = $data['price'];
                $type = 3;
                break;
            case $order_type == 6:
                $pay_des = '准了 - 教学视频';
                $data = $this->pay_video(['id' => $id]);
                $price = $data['price'];
                $gid = $data['gid'];
                $type = 4;
                break;
            default :
                return show(config('code.error'), '下单商品信息有误,请重新下单');
        }

        // 生成唯一订单号  011806192149570386 01校准生辰 02运势 03幸运之城 04教学视频 05问答 06围观
        $out_trade_no = str_pad($type, 2, '0', STR_PAD_LEFT) . date('YmdHis') . str_pad(random_int(1, 9999), 4, '0', STR_PAD_LEFT);

        // VIP 价格全部 0.01元
        $vipLevel = Util::getVips($uid, $map['order_type'], $rid,$gid);
        if ($rids)
        {
            $rids = explode(',', $rids);
        } else
        {
            $rids = [];
        }

        if ($vipLevel)
        {
            $price = 0.01;
        }

        //新订单表生成数据
//        $this->insertNewOrder(['reid'=>$reid,'trade_type'=>$trade_type,'order_type'=>$order_type,'gctid'=>$gid,'gctids'=>$gids,'rid'=>$rid,'rids'=>$rids,'order_id'=>$out_trade_no,'total_amount'=>$price,'fortune_type'=>$fortune_type,'fortune_time'=>$start_time]);

        $price = sprintf('%.2f', $price);

        /**
         * $account int 下单使用的商户配置id
         * 支付方式   1=>支付宝，2=>微信支付，5=>京东支付，6=>微信公众号支付，7=>支付宝手机网页支付，8=>微信H5网页支付
         */
        switch ($trade_type)
        {
            case 7:
            case 1:
                $account = (int)config('alipay.default');
                break;
            case 6:
            case 8:
            case 2:
                $account = (int)config('wxpay.default');
                break;
            case 5:
                $account = (int)config('jdpay.default');
                break;
            default:
                $account = 1;
                break;
        }

        $insert = [
            'order_type' => $order_type,
            'uid' => $uid,
            'gid' => $gid,
            'order_id' => $out_trade_no,
            'reid' => $reid,
            'fid' => $fid,
            'trade_type' => $trade_type,
            'total_amount' => $price,
            'create_time' => $time,
            'status' => 0,
            'account' => $account
        ];

        $OrderModel = new Orders();
        $orderCacheModel = new \app\common\cachemodel\Orders();
        // 生成订单到数据库
        try
        {
            $oid = $orderCacheModel->SaveData($insert);
        }
        catch (Exception $e)
        {
            Log::write($e->getMessage(), 'error');
            throw new ApiException('下单失败,请重新操作');
        }

        if ($type === 3)
        {
            $this->addInfo($oid, $gids, $rid);
        }
        // 删除订单缓存
        $OrderModel->rm_cache(['uid' => $uid, 'del_add' => 1, 'order_id' => $out_trade_no]);

        //支付订单
        $arr = (new OrdersLib())->unifyPayOrder([
            'oid' => $oid,
            'trade_type' => $trade_type,
            'total_amount' => $price,
            'pay_des' => $pay_des,
            'order_id' => $out_trade_no,
            'openid' => $openid,
            'callback_url' => $callback_url,
            'order_type' => $order_type
        ], 1);

        if ($gid)
        {
            $skuId = 'apple_pay_' . $gid;
        } else
        {
            $new_gid = [];
            foreach ($gids as $gid)
            {
                $new_gid[] = 'apple_pay_' . $gid;
            }
            $skuId = implode(',', $new_gid);
        }

        //更新订单详情缓存
        $orderCacheModel->UpdateCache($out_trade_no, 0);
        $arr['data']['skuId'] = $skuId;

        return $arr;
    }

    /**
     * 校准生辰下单,获取商品信息
     * @param array $map
     * @return Json
     * @throws ApiException
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function pay_rec($map = [])
    {
        /**
         * 5秒内频繁操作过滤
         */
        if (Cache::get($this->user['id'] . ':pay:rec'))
        {
            throw new ApiException('操作频繁,请稍候再试');
        }

        Cache::set($this->user['id'] . ':pay:rec', 1, 5);

        $gid = (int)$map['gid'];
        (int)$id = $map['reid'] ?? 0;// 商品id =>校准生辰id

        $OrdersModel = new Orders();
        $GoodsModel = new Goods();

        //检测改校准生辰是否有未支付订单,有就删除该笔订单
        try
        {
            Db::table('wechat_backup_07_18_14_43_00.app_orders')->where(['reid' => $id, 'status' => 0])->update(['is_del' => 1]);
        }
        catch (Exception $e)
        {
            Log::write('校准生辰下单修改未支付订单状态失败:' . $e->getMessage(), 'error', true);
        }
        //检测改校准生辰是否有已支付订单，有就提示用户
        if ($OrdersModel->where(['reid' => $id, 'status' => 1])->find())
        {
            throw new ApiException('您已支付该笔订单，请查看订单。');
        }
        try
        {
            if ($this->is_apple_pay)
            {
                $goods = $this->apple_goods['rec_goods'][0];
            } else
            {
                // 商品金额信息
                $goods = $GoodsModel->getGoodsRec(['id' => $gid]);
            }

        }
        catch (Exception $e)
        {
            throw new ApiException('获取校准生辰商品信息失败');
        }
        //检测当前购买商品是否存在
        if (!$goods)
        {
            throw new ApiException('商品不存在');
        }

        // 重组支付价格
        if (isset($goods['discount']) && $goods['discount'] > 0)
        {
            $price = $goods['or_prize'] * (float)$goods['discount'];

        } else
        {
            //获取活动折扣
            $activeDiscount = active($map['gid']);
            if ($activeDiscount['discount'] && !$this->is_apple_pay)
            {
                $price = sprintf('%.2f', $goods['now_prize'] * $activeDiscount['discount']);
            } else
            {

                $price = $goods['now_prize'];
            }
        }

        $arr['price'] = $price;

        return $arr;
    }

    /**
     * 运势下单,获取商品信息
     * @param array $map
     * @return array|Json
     * @throws ApiException
     * @throws Exception
     */
    public function pay_fortune($map = [])
    {
        if (Cache::get($this->user['id'] . ':pay:fortune'))
        {
            throw new ApiException('操作频繁,请稍候再试');
        }

        Cache::set($this->user['id'] . ':pay:fortune', 1, 5);

        // 商品类型id   1=>校准生辰
        $gid = (int)$map['gid'];
        // 选择的档案id，字符串
        $rids = $map['rids'];
        $arid = count(explode(',', $rids));
        // 选择的解锁日期,字符串类型
        $start_time = $map['start_time'];
        //运势类型id
        $fortune_type = $map['fortune_type'];

        $goods_model = new Goods();

        $CheckOrders = new CheckOrders();

        //判断下单时间格式是否正确,获取下单时间的时间戳
        switch ($fortune_type)
        {
            case 1:
                if ($this->is_apple_pay)
                {
                    $goodes = $this->apple_goods['fortune_day_goods'];
                } else
                {
                    $goodes = $goods_model->getGoodsForDay(['id' => 2]);
                }
                break;
            case 2:
                if ($this->is_apple_pay)
                {
                    $goodes = $this->apple_goods['fortune_month_goods'];
                } else
                {
                    $goodes = $goods_model->getGoodsForMonth(['id' => 20]);
                }
                break;
            case 3:
                if ($this->is_apple_pay)
                {
                    $goodes = $this->apple_goods['fortune_year_goods'];
                } else
                {

                    $goodes = $goods_model->getGoodsForYear(['id' => 24]);
                }
                break;
            default :
                $goodes = [];
                break;
        }

        $fortune_time = Util::FormatFortuneTime($fortune_type + 1, $start_time, $gid);

        // 暂时关闭2019年运购买
//        \app\common\cachemodel\OrdersLib::CloseOrderFortuneTime($fortune_type + 1, $fortune_time['start_time']);

        //检查当前档案是否已有当前订单
        $CheckOrders->check_fortunes(['uid' => $this->user['id'], 'rids' => $rids, 'start_time' => $fortune_time['start_time'], 'end_time' => $fortune_time['end_time'], 'gid' => $gid, 'fortune_type' => $fortune_type]);

        $goods = [];
        foreach ($goodes as $v)
        {
            if ($v['id'] == $gid)
            {
                $goods = $v;
            }
        }

        if (!$goods || empty($goods))
        {
            return show(config('code.error'), '商品不存在');
        }

        //检查是否在活动时间内,买一赠一
        $active = false;
        $fortuneData = ['rids' => $rids, 'start_time' => $fortune_time['start_time'], 'goods' => $goods, 'active' => $active, 'fortune_type' => $fortune_type];
        //  将档案信息存入新表
        $fid = $this->addrecode($fortuneData);

        // 重组支付价格
        if (isset($goods['discount']) && $goods['discount'] > 0)
        {
            $price = (float)($goods['or_prize'] * $goods['discount']);
        } else
        {
            //获取活动折扣
            $activeDiscount = active($map['gid'], $map['start_time']);
            if ($activeDiscount['discount'] && !$this->is_apple_pay)
            {
                $price = sprintf('%.2f', $goods['now_prize'] * $activeDiscount['discount']);
            } else
            {

                $price = $goods['now_prize'];
            }
        }

        $pay_price = $price * $arid;

        return [
            'fid' => $fid,
            'price' => $pay_price
        ];
    }

    /**
     * 幸运之城下单,获取商品信息
     * @param array $map
     * @return float|int|Json
     * @throws ApiException
     */
    public function pay_map($map = [])
    {
        if (Cache::get($this->user['id'] . ':pay:map'))
        {
            throw new ApiException('操作频繁,请稍候再试');
        }

        Cache::set($this->user['id'] . ':pay:map', 1, 5);

        $gids = $map['gids'];// 商品类型id

        $rid = $map['rid'];// 档案id

        if (!$gids)
        {
            throw new ApiException('请选择商品');
        }
        if (!$rid)
        {
            throw new ApiException('请选择档案');
        }

        $CheckOrder = new CheckOrders();
        $GoodsModel = new Goods();
        //检查是否有支付的订单,提示用户
        $CheckOrder->check_lines_pay(['rid' => $rid, 'gids' => $gids]);
        //检查是否有未支付的订单,删除重新下单
        $CheckOrder->check_lines(['rid' => $rid, 'gids' => $gids]);

        //获取商品信息
        try
        {
            if ($this->is_apple_pay)
            {
                $goods = $this->apple_goods['acg_goods'];
            } else
            {
                $goods = $GoodsModel->getGoodsForACG();
            }
        }
        catch (Exception $e)
        {
            throw new ApiException('商品未找到');
        }
        $goods = json_decode(json_encode($goods, true), true);

        $price = 0;
//        $activeDiscount = false;
        // 重组支付价格
        foreach ($goods as $k => $v)
        {
            if (in_array($v['id'], $gids))
            {
                $activeDiscount = active($v['id']);
                if ($activeDiscount['discount'] && !$this->is_apple_pay)
                {
                    $price_temp = (string)($v['now_prize'] * $activeDiscount['discount'] * 100);
                    $price += (int)$price_temp / 100;
                } else
                {
                    $price += (int)$v['now_prize'];
                }
            }
        }
        if (!$price)
        {
            throw new ApiException('服务异常，请稍后再试');
        }


//        if ($activeDiscount['discount'] && !$this->is_apple_pay)
//        {
////            $price = sprintf('%.2f', $price * $activeDiscount['discount']);
//            $price = floor($price * $activeDiscount['discount'] * 100) / 100;
//        }

        $arr['price'] = (string)$price;

        return $arr;
    }

    /**
     * 教学视频下单,获取商品信息
     * @param array $map
     * @return Json
     * @throws ApiException
     */
    public function pay_video($map = [])
    {
        if (Cache::get($this->user['id'] . ':pay:video'))
        {
            throw new ApiException('操作频繁,请稍候再试');
        }

        Cache::set($this->user['id'] . ':pay:video', 1, 5);

        $id = $map['id'];// 课程id

        $uid = $this->user['id'];

        //验证请求参数
        if (!$id)
        {
            throw new ApiException('请选择购买的视频');
        }

        //检测当前id是否是已上架的视频
        $CourseModel = new ZhunleCourse();
        $course = $CourseModel->getCourseInfo(['id' => $id]);
        if (!$course)
        {
            throw new ApiException('当前视频未上架,请重新选择');
        }
        //获取所有视频的商品信息
        $GoodsModel = new Goods();
        if ($this->is_apple_pay)
        {
            $goods_data = $this->apple_goods['video_goods'];
        } else
        {

            $goods_data = $GoodsModel->getVideoInfo(['id' => $course['gid']]);
        }

        if ($goods_data === false)
        {
            throw new ApiException($GoodsModel->getError());
        }

        $goods = [];
        foreach ($goods_data as $good)
        {
            //获取当前视频的商品信息
            if ($good['id'] == $course['gid'])
            {
                $goods = $good;
            }
        }

        $CheckOrder = new CheckOrders();
        //检查是否有有支付的订单,提示用户
        $CheckOrder->check_prepaid_video(['uid' => $uid, 'gid' => $course['gid']]);
        //检查是否有未支付的订单,将订单原有订单删除
        $CheckOrder->check_unpaid_video(['uid' => $uid, 'gid' => $course['gid']]);

        // 重组支付价格
        if (isset($goods['discount']) && $goods['discount'] > 0)
        {
            $price = (float)($goods['or_prize'] * $goods['discount']);

        } else
        {
            //获取活动折扣
            $activeDiscount = active($goods['id']);
            if ($activeDiscount['discount'] && !$this->is_apple_pay)
            {
                $price = sprintf('%.2f', $goods['now_prize'] * $activeDiscount['discount']);
            } else
            {

                $price = $goods['now_prize'];
            }

        }

        $arr['price'] = $price;
        $arr['gid'] = $goods['id'];

        return $arr;

    }

    /**
     * 将购买运势的档案信息存入新表
     * @param array $map
     * @return int|string
     */
    public function addrecode($map = [])
    {
        $rids = $map['rids'];
        $start_time = $map['start_time'];
        $fortune_type = $map['fortune_type'];

        $arr = [
            'type' => $fortune_type,
            'rids' => $rids,
            'time' => $start_time,
            'create_time' => time(),
        ];
//        $extend = [];
        //若在活动时间内，买一增一
//        if ($active) {
//            $expire_time = $goods['expire_time'];
//            $time = (int)(substr($expire_time, 1, 1)) * 2;
//            $time_str = substr($expire_time, 2, 5);
//
//            $extend = ['expire_time' => '+' . $time . $time_str];
//            $extend = json_encode($extend, true);
//            $arr = [
//                'type' => $fortune_type,
//                'rids' => $rids,
//                'time' => $start_time,
//                'create_time' => time(),
//                'extend' => $extend,
//            ];
//        }

        //每日运势id

        return Db::table('app_fortune')->insertGetId($arr);

    }

    /**
     * 新建订单,生成中间表数据和命格线订单数据
     * @param $oid
     * @param $gids
     * @param $rid
     * @return bool
     * @throws ApiException
     */
    public function addInfo($oid, $gids, $rid)
    {
        $array = [];
        foreach ($gids as $k => $v)
        {
            $array[] = [
                'gid' => $v,
                'oid' => $oid,
                'rid' => $rid
            ];
        }
        //中间表
        try
        {
            Db::table('app_orders_goods')->insertAll($array);
        }
        catch (Exception $e)
        {
            throw new ApiException('下单数据生成失败,请重试');
        }

        return true;
    }
}
